package share

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"io"
	"math"
	"math/rand"
	"strconv"
	"strings"

	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
)

var (
	randStr = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz")
)

func SnakeString(s string) string {
	data := make([]byte, 0, len(s)*2)
	j := false
	num := len(s)
	for i := 0; i < num; i++ {
		d := s[i]
		// or通过ASCII码进行大小写的转化
		// 65-90（A-Z），97-122（a-z）
		//判断如果字母为大写的A-Z就在前面拼接一个_
		if i > 0 && d >= 'A' && d <= 'Z' && j {
			data = append(data, '_')
		}
		if d != '_' {
			j = true
		}
		data = append(data, d)
	}
	//ToLower把大写字母统一转小写
	return strings.ToLower(string(data[:]))
}

// Md5Byte 计算md5，返回字节
func Md5Byte(str string) []byte {
	h := md5.New()
	buf := []byte(str)
	count, err := h.Write(buf)
	if err != nil || count != len(buf) {
		return nil
	}
	return h.Sum(nil)
}

// Md5Str 计算md5，返回字符串
func Md5Str(str string) string {
	return hex.EncodeToString(Md5Byte(str))
}

// Decimal 保留几位小数
func Decimal(value float64, num int) float64 {
	format := "%." + strconv.Itoa(num) + "f"
	value, _ = strconv.ParseFloat(fmt.Sprintf(format, value), 64)
	return value
}

func Round(val float64, precision int) float64 {
	p := math.Pow10(precision)
	return math.Floor(val*p+0.5) / p
}

// RandString 生成随机字符串
func RandString(l int) string {
	result := []byte{}
	for i := 0; i < l; i++ {
		result = append(result, randStr[rand.Intn(len(randStr))])
	}
	return string(result)
}

func GbkToUtf8(s []byte) ([]byte, error) {
	reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
	d, err := io.ReadAll(reader)
	if err != nil {
		return nil, err
	}
	return d, nil
}

func Contains[T ~int | ~int8 | ~int16 | ~int32 | ~int64 |
	~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 |
	~float32 | ~float64 |
	~string](value T, list []T) bool {
	for _, one := range list {
		if value == one {
			return true
		}
	}

	return false
}
